package net.zdsoft.wpchat.support.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;

import net.zdsoft.keel.cache.KeyMaker;
import net.zdsoft.keel.jdbc.JdbcBasicDao;
import net.zdsoft.keel.jdbc.MultiRowMapper;
import net.zdsoft.keel.jdbc.SqlCreator;
import net.zdsoft.keel.util.Validators;
import net.zdsoft.wpchat.support.dao.AuthGroupDao;
import net.zdsoft.wpchat.support.entity.AuthGroup;
import net.zdsoft.wpchat.support.entity.AuthGroupUser;
import net.zdsoft.wpchat.support.entity.Operator;
import net.zdsoft.wpchat.support.enums.AuthGroupTypeEnum;

/**
 * 群组dao实现
 * 
 * @author xuan
 */
@Repository
public class AuthGroupDaoImpl extends JdbcBasicDao implements AuthGroupDao {
    private static final String SQL_FIND_GROUP = "SELECT * FROM su_group";
    private static final String SQL_INSERT_GROUP = "INSERT INTO su_group(id, name, type, description, modify_time, creation_time) VALUES(?,?,?, ?, ?, ?)";
    private static final String SQL_UPDATE_GROUP = "UPDATE su_group SET name=?, description=?, modify_time=? WHERE id=?";
    private static final String SQL_DELETE_GROUP_BY_ID_IN = "DELETE FROM su_group WHERE id IN";
    private static final String SQL_FIND_GROUP_USERS = "SELECT sgo.group_id, so.id,"
            + "so.login_name, so.name,  so.state, " + "so.creation_time FROM su_group_operator sgo,su_operator so"
            + "WHERE sgo.operator_id = so.id ";

    @Override
    public List<AuthGroup> findByIds(String... groupIds) {
        if (Validators.isEmpty(groupIds)) {
            return Collections.emptyList();
        }

        return queryForInSQL(SQL_FIND_GROUP + " WHERE id IN", null, groupIds, new GroupMultiRowMapper());
    }

    @Override
    public List<AuthGroup> findAll() {
        return query(SQL_FIND_GROUP, new GroupMultiRowMapper());
    }

    @Override
    public void insertGroup(AuthGroup authGroup) {
        if (Validators.isEmpty(authGroup.getId())) {
            authGroup.setId(createId());
        }

        update(SQL_INSERT_GROUP,
                new Object[] { authGroup.getId(), authGroup.getName(), authGroup.getType(), authGroup.getDescription(),
                        authGroup.getModifiedTime(), authGroup.getCreationTime() });
    }

    @Override
    public void updateGroup(AuthGroup authGroup) {
        update(SQL_UPDATE_GROUP,
                new Object[] { authGroup.getName(), authGroup.getDescription(), authGroup.getModifiedTime(),
                        authGroup.getId() });
    }

    @Override
    public void deleteGroup(String... groupIds) {
        if (Validators.isEmpty(groupIds)) {
            return;
        }

        updateForInSQL(SQL_DELETE_GROUP_BY_ID_IN, null, groupIds);
    }

    @Override
    public Map<String, List<AuthGroupUser>> findGroupUsers() {
        List<AuthGroupUser> groupUserlist = query(SQL_FIND_GROUP_USERS, new MultiRowMapper<AuthGroupUser>() {
            @Override
            public AuthGroupUser mapRow(ResultSet rs, int rowNum) throws SQLException {
                AuthGroupUser groupUser = new AuthGroupUser();
                groupUser.setGroupIds(new String[] { rs.getString("group_id") });
                groupUser.setOperator(new OperatorMultiReader().mapRow(rs, rowNum));
                return groupUser;
            }

        });
        Map<String, List<AuthGroupUser>> map = new HashMap<String, List<AuthGroupUser>>();

        for (int i = 0; i < groupUserlist.size(); i++) {
            AuthGroupUser groupUser = groupUserlist.get(i);

            String key = KeyMaker.getKey(groupUser.getGroupIds());
            List<AuthGroupUser> _groupUserlist = null;
            if (map.containsKey(key)) {
                _groupUserlist = map.get(key);
            }
            else {
                _groupUserlist = new ArrayList<AuthGroupUser>();
                map.put(key, _groupUserlist);
            }
            _groupUserlist.add(groupUser);
        }

        return map;
    }

    @Override
    public List<AuthGroup> findByType(AuthGroupTypeEnum type) {
        if (type == null) {
            return Collections.emptyList();
        }
        SqlCreator creator = new SqlCreator(SQL_FIND_GROUP, false);
        creator.and("type = ?", type.getValue(), true);
        return query(creator.getSQL(), creator.getArgs(), new GroupMultiRowMapper());
    }

    /**
     * 后台用户多条结果集
     * 
     * @author xuan
     */
    public static class OperatorMultiReader implements MultiRowMapper<Operator> {
        @Override
        public Operator mapRow(ResultSet rs, int rowNum) throws SQLException {
            Operator operator = new Operator();
            operator.setId(rs.getString("id"));
            operator.setName(rs.getString("name"));
            operator.setState(rs.getInt("state"));
            operator.setCreationTime(rs.getTimestamp("creation_time"));
            operator.setLoginName(rs.getString("login_name"));
            return operator;
        }
    }

    /**
     * 群组多条结果集
     * 
     * @author xuan
     */
    private static class GroupMultiRowMapper implements MultiRowMapper<AuthGroup> {
        @Override
        public AuthGroup mapRow(ResultSet rs, int rowNum) throws SQLException {
            AuthGroup group = new AuthGroup();
            group.setId(rs.getString("id"));
            group.setName(rs.getString("name"));
            group.setType(rs.getInt("type"));
            group.setCreationTime(rs.getTimestamp("creation_time"));
            group.setDescription(rs.getString("description"));
            group.setModifiedTime(rs.getTimestamp("modify_time"));
            return group;
        }
    }

}
